[2.0] fixes on schema and test resources - #1001
Conversation
a03e560 to
905e58a
Compare
- [x] Java tests - functional - [x] JS tests - functional - WIP - found some false-positives/false-negatives - due to errors in test resources - [x] JS tests - schema validate - includes #996 - includes #992 - JS tests - semantics - [x] #998 - [x] #995 - [x] PHP tests - functional added tests only, no schema/res fixes - they are prepared in - #997 - #1001 --------- Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
There was a problem hiding this comment.
Pull request overview
Updates the CycloneDX 2.0 JSON schemas and test fixtures to align with recent model changes (notably parties, signatures, extensible properties, and stricter schema semantics), and extends the JS semantic test suite to enforce additional schema invariants.
Changes:
- Refactors many 2.0 test resources from legacy fields (e.g.,
publisher,supplier,manufacturer,authors,signature) to 2.0 structures (parties,signatures), and corrects cryptography-related shapes. - Tightens/clarifies schema semantics (e.g.,
additionalProperties: falsein more places, explicit property presence inoneOf/anyOfbranches,refLinkTypeusage). - Adds extensible-properties valid/invalid fixtures and adjusts JS semantic tests for the updated schema patterns.
Reviewed changes
Copilot reviewed 49 out of 49 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/src/test/resources/2.0/valid-standard-2.0.json | Updates signature fixture to signatures[] and new JSS field names. |
| tools/src/test/resources/2.0/valid-service-2.0.json | Migrates publisher to parties role-based representation. |
| tools/src/test/resources/2.0/valid-perspective-2.0.json | Migrates supplier to parties role-based representation. |
| tools/src/test/resources/2.0/valid-patent-2.0.json | Migrates manufacturer to parties and updates organization URL structure. |
| tools/src/test/resources/2.0/valid-machine-learning-considerations-env-2.0.json | Migrates supplier/publisher to parties. |
| tools/src/test/resources/2.0/valid-machine-learning-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-name-with-text-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-name-with-licensing-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-name-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-id-with-text-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-id-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-expression-with-licensing-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-expression-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-license-choice-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-formulation-2.0.json | Migrates publisher to parties. |
| tools/src/test/resources/2.0/valid-external-reference-2.0.json | Migrates publisher to parties and adds new externalReference types. |
| tools/src/test/resources/2.0/valid-extensible-properties.json | Adds a valid extensible-properties fixture (new file). |
| tools/src/test/resources/2.0/valid-cryptography-implementation-2.0.json | Updates cryptography fixtures to match schema (e.g., arrays where required). |
| tools/src/test/resources/2.0/valid-cryptography-full-2.0.json | Updates cryptography fixtures (e.g., arrays for refs/platform). |
| tools/src/test/resources/2.0/valid-cryptography-certificate-advanced-2.0.json | Updates certificate fixtures and adds algorithm asset + algorithmRef arrays. |
| tools/src/test/resources/2.0/valid-cryptography-certificate-2.0.json | Fixes ref and expands crypto assets; updates platform arrays. |
| tools/src/test/resources/2.0/valid-component-swid-full-2.0.json | Migrates authors to parties with author role. |
| tools/src/test/resources/2.0/valid-component-swid-2.0.json | Migrates authors to parties with author role. |
| tools/src/test/resources/2.0/valid-component-choice-xor-2.0.json | Migrates supplier to parties for component-choice samples. |
| tools/src/test/resources/2.0/valid-component-choice-or-2.0.json | Migrates supplier to parties for component-choice samples. |
| tools/src/test/resources/2.0/valid-component-choice-nested-2.0.json | Migrates nested supplier to nested parties. |
| tools/src/test/resources/2.0/valid-component-choice-in-nested-components-2.0.json | Migrates nested supplier to nested parties. |
| tools/src/test/resources/2.0/valid-component-choice-and-2.0.json | Migrates supplier to parties for AND operator sample. |
| tools/src/test/resources/2.0/valid-bom-2.0.json | Broad migration of manufacturer/supplier/authors/publisher to parties, including contacts and URLs. |
| tools/src/test/resources/2.0/valid-attestation-2.0.json | Migrates multiple signature objects to signatures[] throughout. |
| tools/src/test/resources/2.0/invalid-extensible-properties.json | Adds invalid extensible-properties fixture (new file). |
| tools/src/test/resources/2.0/invalid-component-choice-missing-name-2.0.json | Removes an invalid test resource fixture. |
| tools/src/test/js/schema-v2/json-schema-semantic-tests.js | Updates semantic tests for refLinkType exception and additionalProperties handling. |
| schema/2.0/model/cyclonedx-vulnerability-2.0.schema.json | Adds additionalProperties: false and fixes required-property existence assertions. |
| schema/2.0/model/cyclonedx-patent-2.0.schema.json | Switches certain refs from refType to refLinkType. |
| schema/2.0/model/cyclonedx-party-2.0.schema.json | Makes oneOf branches explicitly assert the required property exists. |
| schema/2.0/model/cyclonedx-metadata-2.0.schema.json | Adds additionalProperties: false to an object schema. |
| schema/2.0/model/cyclonedx-license-2.0.schema.json | Makes oneOf branches explicitly assert the required property exists. |
| schema/2.0/model/cyclonedx-jss_X590_2023_10-2.0.schema.json | Consolidates millisecond timestamp handling and adds explicit property presence in anyOf. |
| schema/2.0/model/cyclonedx-formulation-2.0.schema.json | Makes oneOf branches explicitly assert the required property exists. |
| schema/2.0/model/cyclonedx-declaration-2.0.schema.json | Adjusts required fields in a oneOf branch (e.g., signatures). |
| schema/2.0/model/cyclonedx-data-2.0.schema.json | Makes oneOf branches explicitly assert the required property exists. |
| schema/2.0/model/cyclonedx-cryptography-2.0.schema.json | Refactors some oneOf branches/types and shifts refs to refLinkType. |
| schema/2.0/model/cyclonedx-component-2.0.schema.json | Improves mutual-exclusion logic annotation and adds property presence to not. |
| schema/2.0/model/cyclonedx-common-2.0.schema.json | Makes refLinkType inheritance explicit; refactors extensible-properties schema; adjusts base mixins; adds placeholder for organizationalEntityOrContact. |
| schema/2.0/model/cyclonedx-citation-2.0.schema.json | Makes anyOf/oneOf branches explicitly assert required property exists. |
| schema/2.0/model/cyclonedx-annotation-2.0.schema.json | Makes oneOf branches explicitly assert required property exists. |
| schema/2.0/model/cyclonedx-ai-modelcard-2.0.schema.json | Removes redundant type alongside $ref. |
| schema/2.0/cyclonedx-2.0.schema.json | Replaces root additionalProperties: false with unevaluatedProperties: false to support extensibility mixins. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
removed the test case, since the name was not required at all ...
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
|
had Fable 5 analyze the state of the schema. my query: report: CycloneDX 2.0 JSON Schema Structure ReviewScope: branch 1. Broken / fragile referencesAll intra-
2.
|
| Location | Issue | Suggested fix |
|---|---|---|
model/cyclonedx-common-2.0.schema.json#/$defs/organizationalEntityOrContact |
Literally {"$comment": "TODO"} — an unfinished stub. |
Implement or delete. |
model/cyclonedx-common-2.0.schema.json#/$defs/timestamp |
Unused, while 48 places across the corpus inline "format": "date-time" without a pattern. In 2020-12, format is annotation-only by default, so those 48 timestamps are effectively unvalidated, and the one def that does validate (format + pattern) is dead. |
Ref common#/$defs/timestamp everywhere (or delete it and accept format-only). |
model/cyclonedx-common-2.0.schema.json#/$defs/base64 |
Unused; common#/$defs/attachment declares encoding: enum ["base64"] but never validates content against this pattern. |
Wire it into attachment (e.g. via if/then on encoding) or delete. |
model/cyclonedx-common-2.0.schema.json#/$defs/baseObject |
The "mixin base object for all CycloneDX entities" (composes extensibleProperties) is dead code — nothing refs it. Consequence: only the document root composes extensibleProperties; every other object is closed with additionalProperties: false, so the ext:<namespace>:<name> extension mechanism is unusable anywhere except the BOM top level. |
Either have entity defs compose baseObject/extensibleProperties + unevaluatedProperties: false, or delete baseObject and document that extensions are root-only. |
4. Circular references & duplicate definitions
- File-level cycle:
cyclonedx-component-2.0.schema.json⇄cyclonedx-ai-modelcard-2.0.schema.json(component →modelCard,graphicsCollection; ai-modelcard →componentData). Fully resolvable for validators — not problematic, but worth knowing for code generators. Self-recursive defs (nestedcomponents,dependencygraph, etc.) are standard and fine. - Duplicate
$defsnames across files (14):dependency,flow,hashAlgorithm,identifier(×3),metadata,postalAddress,rating,requirement,requirements,risk,signatures,step,timestamp,trigger.- True concept duplicate:
postalAddressincommonvsparty— thepartyversion is a superset (addsisoCode,coordinates). Two competing address models. Fix: keep one (party's) and ref it; delete/alias the other. - Intentional but collision-prone:
hashAlgorithmandtimestampincyclonedx-jss_X590_2023_10deliberately differ fromcommon(IANA names / X.590 clause 6.1 millisecond rule). Fine semantically, but same-named defs across files will clash in naive bundlers/codegen. Fix: prefix jss defs (e.g.jssTimestamp) or namespace during bundling. - The rest (
dependencyin dependency vs requirement,flow,metadata,identifier,rating,risk,step,trigger, …) are genuinely different domain concepts sharing generic names — acceptable, same bundling caveat.
- True concept duplicate:
5. Draft 2020-12 correctness
- Metaschema validation: 0 violations in all 36 files. ✅
- Regex patterns: all
pattern/patternPropertiescompile. ✅ - Root composition (
unevaluatedProperties: false+allOf: [$ref → common#/$defs/extensibleProperties]): works as intended. In 2020-12,unevaluatedPropertiessees annotations frompatternPropertiesinside schemas reached throughallOf/$ref, soext:…properties are correctly allowed at the root while unknown properties are rejected. ✅ additionalProperties: false+allOfcombinations (e.g.component#/$defs/component,behavior#/$defs/behaviorGraph|behaviorNode,vulnerability#/$defs/presenceEvidence,threatcategories): verified that noallOfbranch introduces property names absent from the parent'sproperties— all branches arenot/if-thenconstraints on declared properties, so nothing is falsely rejected. ✅ However, this closes those objects toext:extensions (see §3baseObject) and mixes two closure idioms (additionalProperties: falsevs the root'sunevaluatedProperties: false). Suggested fix: standardise on one idiom per the intended extensibility model.$schemadeclarations: present and correct in every file. ✅ No legacy keywords (definitions, booleanexclusiveMinimum,additionalItems) anywhere. ✅ (cyclonedx-definition-2.0.schema.json#/$defs/definitionsis a def named "definitions", not the keyword — legal, mildly confusing.)specVersionis unconstrained:cyclonedx-2.0.schema.json#/properties/specVersionis required but has onlyexamples: ["2.0"]— any string validates. 1.x schemas pinned it withenum. Fix: add"const": "2.0"(or an enum/pattern).- Single-value enums (prefer
const):cyclonedx-2.0.schema.json#/properties/specFormat(["CycloneDX"]),ai-modelcard#/$defs/energyMeasure/properties/unit(["kWh"]),ai-modelcard#/$defs/co2Measure/properties/unit(["tCO2eq"]),common#/$defs/attachment/properties/encoding(["base64"]),evidence#/$defs/assessmentMethod/allOf/1/.../not(["filename"]). Cosmetic. jss…#/$defs/signatureObjectsetsunevaluatedProperties: true: redundant (open is the default) but intentional and documented via$commentciting X.590 clause 6.2. OK as-is.- Non-standard
meta:enumkeyword: used consistently and everymeta:enumkey set exactly matches its siblingenumvalues ✅ (established CycloneDX 1.6/1.7 convention).
6. Naming / structural inconsistencies
| Location | Issue | Suggested fix |
|---|---|---|
model/cyclonedx-jss_X590_2023_10-2.0.schema.json |
Not a typo: ITU‑T X.590 (2023‑10) is the JSON Signature Scheme (JSS) — distinct from X.509; common#/$defs/signatures even links the ITU X.590 publication. Only the style is inconsistent: underscores + embedded date vs the hyphenated, undated names of every other file. |
Optionally rename to e.g. cyclonedx-jss-x590-2.0.schema.json for consistency. |
jss signatureObject properties |
snake_case (hash_algorithm, public_key, cert_url, valid_from, …) vs camelCase everywhere else — intentional (X.590 wire format), but worth a $comment if not already obvious. |
Document; keep as-is. |
| Root container shape inconsistency | components, dependencies, compositions, vulnerabilities, controls, annotations, formulation, blueprints, citations, perspectives are arrays, but threats, risks, declarations, definitions, profiles are objects wrapping same-named arrays (bom.threats.threats[], bom.risks.risks[]). |
Accept (matches 1.6 declarations precedent) or flatten for uniformity; at minimum document the convention. |
26 of 307 $defs lack title |
e.g. common#/$defs/refType, refLinkType, component#/$defs/version, versionRange, componentData, composition#/$defs/aggregateType, formulation#/$defs/step, command, … |
Add titles for doc-generation consistency. |
schema/2.0/README.md |
Table references cyclonedx-api-2.0-bundled.schema.json, which does not exist. |
Create it or remove the row. |
schema/2.0/model/README.md |
Badly stale: lists 4 nonexistent files (cyclonedx-ai-model-parameters, cyclonedx-licensing, cyclonedx-patent-assertion, cyclonedx-patent-family) and omits ~16 real files (behavior, blueprint, business-objective, certification, citation, control, data, evidence, jss, party, perspective, physical, profile, requirement, risk, threat, usecase, weakness). |
Regenerate the model index. |
component#/$defs/component/properties/mime-type |
Kebab-case like legacy bom-ref; everything else camelCase. |
Accept as 1.x-compat or rename (mimeType) since 2.0 is a breaking release. |
7. Explicitly checked and found fine
- ✅ All 36 files parse as valid JSON and validate against the draft 2020-12 metaschema (0 errors).
- ✅ All intra-
schema/2.0$refs (file +#/$defs/...pointer) resolve; all pointers into external files (#/definitions/...) also exist. - ✅
$id↔ path/filename convention correct in all 36 files;$schemapresent everywhere. - ✅ No orphaned model files — every model file is reachable from the root schema.
- ✅ Root
unevaluatedProperties: false+allOf → extensiblePropertiescomposition behaves correctly under 2020-12 annotation rules. - ✅ No
additionalProperties: falseobject is broken by itsallOfbranches (no branch declares undeclared property names). - ✅ All regexes compile;
serialNumberurn:uuid pattern is correct;patternProperties^ext:...$anchored correctly. - ✅ No
requiredentries missing frompropertiesin closed objects; no duplicaterequiredentries; no unknownformatvalues; no$refsiblings that add conflicting constraints;meta:enumfully consistent withenumeverywhere;$defsnames uniformly lowerCamelCase. - ✅
jss_X590filename is not an X.509 typo — it correctly references ITU-T X.590 (JSS), edition 2023-10.
Priority fixes (summary)
- Fix
httpvshttps$idmismatch inschema/cryptography-defs.schema.jsonandschema/spdx.schema.json(breaks$id-based ref resolution from 2.0). - Resolve the dead extensibility design: orphaned
baseObject+ closed objects meansext:properties only work at the BOM root. - Implement or clearly stub
cyclonedx-api-2.0.schema.json; add the missingcyclonedx-api-2.0-bundled.schema.jsonor fix the README. - Finish or remove
common#/$defs/organizationalEntityOrContact(TODOstub); wire up or remove orphanedtimestamp/base64defs (and addpatternto the 48 unvalidateddate-timefields if strict validation is intended). - Constrain
specVersion(e.g.const: "2.0"). - Deduplicate
postalAddress(common vs party); regeneratemodel/README.md.
actions taken:
- will not do. the schema has an existing and working and in-use ID
- might consider - not in the scope of this PR
- out of scope for this PR
- out of scope of this PR
- not planned. it is a free string that needs to stay like this for compatibility reasons with future/previous releases.
-
postalAddress?? need to look into this - porobably out of the scope of this PR- out odscope - see [2.0] docs: update schema/2.0/model/README.md #1035
|
2 issues flagged by AI (please check if this is valid and relevant, happy to open separate issues if needed):
Edit: Moved to #1037 following comments below. |
fixes or related to
additionalProperties=false#995requiredproperties actually exist #996bom-refmust be of typerefType#998see also:
besides those fixes above, this is in the PR:
refLinkTypeinherit explicitextensibleProertiesJSS$commentsextensiblePropertiesinvalid-component-choice-missing-name-2.0.json- as thenamewas optional or did not exist.❓ was this intentional/correct
tests for the things are based on: